import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { PayOrder } from './payOrder.entity';
import { Goods } from 'src/goods/goods.entity';
import { PayOrderCreateDao } from './interfaces/payLogic.interce';
import { Repository } from 'typeorm';
import { payLogicDomain } from 'src/config/pay';
import { ORDER_STATUS } from 'src/common/const/const';
import { genTransactionId } from 'src/common/utils/base';
import { genPayLogicSign } from 'src/common/utils/base';
import axios from 'axios';
import { GoodsNotFoundError, PayOrderFoundError, GoodsRepeatablePurchaseError } from 'src/common/utils/error';
import { payLogicProjectName } from 'src/config/pay';
import { CreateLogicPayOrderDto } from './dto/payOrder.dto';
import { serviceInfoLog,serviceErrorLog } from "src/common/out/logger/access.logger";

@Injectable()
export class PayOrderService {
    constructor(
        @InjectRepository(PayOrder)
        private payOrderRepository: Repository<PayOrder>,
        @InjectRepository(Goods)
        private goodsRepository: Repository<Goods>,
    ) { }

    async createPayOrder(userid, goodsId, payType, payChannelUser) {
        const goods = await this.goodsRepository.findOne({ where: { id: goodsId } });
        // 校验商品是否存在
        if (!goods) {
            serviceErrorLog(`createPayOrder error, goods not found, goodsId: ${goodsId}`)
            throw new GoodsNotFoundError(goodsId)
        }
        // 校验商品是否可以重复购买
        if (!goods.isRepurchaseable) {
            const existOrder = await this.payOrderRepository.findOne({ where: { goodsId: goods.id, status: ORDER_STATUS.SUCCEED } })
            if (existOrder) {
                return new GoodsRepeatablePurchaseError(goodsId)
            }
        }

        // 请求 payLogic 创建订单 
        const transactionId = genTransactionId()
        const amount = goods.price
        const response = await this.payLogicCreateOrder({
            projectName: payLogicProjectName,
            payType: payType,
            payChannelUser: payChannelUser,
            outTradeNo: transactionId,  // 日记的 transactionId 作为 payLogic 的 outTradeNo
            amount: amount,
        })

        const outTradeNo = response.transaction_id
        const payParams = JSON.stringify(response.pay_params)
        const payOrderCreateDao: PayOrderCreateDao = {
            userid: userid,
            goodsId: goodsId,
            transactionId: transactionId,
            outTradeNo: outTradeNo, // payLogic 的 transactionId 作为日记的 outTradeNo
            payParams: payParams,
            payType: payType,
            payChannelUser: payChannelUser,
            amount: amount,
            status: ORDER_STATUS.INIT,
        };
        const newPayOrder = await this.payOrderRepository.save(payOrderCreateDao);
        serviceInfoLog(`createPayOrder, save payOrder: ${JSON.stringify(payOrderCreateDao, null, 2)}`);

        return {
            "status": newPayOrder.status,
            "transactionId": newPayOrder.transactionId,
            "payParams": newPayOrder.payParams
        }
    }


    async payLogicCreateOrder(createLogicPayOrderDto: CreateLogicPayOrderDto) {
        const data = {
            "project_name": createLogicPayOrderDto.projectName,
            "pay_type": createLogicPayOrderDto.payType,
            "pay_channel_user": createLogicPayOrderDto.payChannelUser,
            "out_trade_no": createLogicPayOrderDto.outTradeNo,
            "amount": createLogicPayOrderDto.amount,
        }
        data['sign'] = genPayLogicSign(data)
        serviceInfoLog(`payLogicCreateOrder, post data: ${JSON.stringify(createLogicPayOrderDto, null, 2)}`)
        try {
            const response = await axios.post(`${payLogicDomain}/api/v1/pay/order`, data);
            serviceInfoLog(`payLogicCreateOrder success, response.data: ${JSON.stringify(response.data, null, 2)}`);
            return response.data;
        } catch (error) {
            serviceErrorLog(`payLogicCreateOrder error, error: ${error}`);
            throw error;  // 抛出错误以便外部可以捕获
        }
    }

    async findByTransactionId(transactionId) {
        const payOrder = this.payOrderRepository.findOne({ where: { transactionId: transactionId } });
        if (!payOrder) {
            throw new PayOrderFoundError();
        }
        return payOrder;
    }
}



